package com.panda.web.service.order.impl;

import com.panda.web.configuration.WxPayConfig;
import com.panda.web.entity.order.WechatOrder;
import com.panda.web.entity.wechat.WechatUser;
import com.panda.web.mapper.order.WechatOrderMapper;
import com.panda.web.mapper.product.OpenidProductMapper;
import com.panda.web.mapper.wechat.WechatUserMapper;
import com.panda.web.mapper.wechatinfo.UserMajorRgppMapper;
import com.panda.web.mapper.wechatinfo.WechatUserinfoMapper;
import com.panda.web.utils.payutils.HttpUtil;
import com.panda.web.utils.payutils.MiniWxPayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class WxPayService {

    private static final String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    @Autowired
    WechatOrderMapper orderMapper;
    @Autowired
    private WxPayConfig wxPayConfig;
    @Autowired
    OpenidProductMapper openidProductMapper;
    @Autowired
    WechatUserMapper wechatUserMapper;
    @Autowired
    WechatUserinfoMapper userinfoMapper;
    @Autowired
    UserMajorRgppMapper userMajorRgppMapper;
    @Transactional
    public Map<String, String> createOrder(WechatOrder order) throws Exception {
        String openid = order.getOpenid();
        WechatUser wechatUserMiniOpenid = wechatUserMapper.findByOpenId(openid);
        String orderId = generateOrderNo(wxPayConfig.getMchId());
        String outTradeNo = orderId;
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", wxPayConfig.getAppId());
        paramMap.put("mch_id", wxPayConfig.getMchId());
        paramMap.put("nonce_str", MiniWxPayUtil.generateNonceStr());
        paramMap.put("body", "body");
        paramMap.put("out_trade_no", outTradeNo);
        paramMap.put("total_fee", String.valueOf(order.getTotalFee().multiply(new BigDecimal(100)).intValue()));
        paramMap.put("spbill_create_ip", "127.0.0.1");
        paramMap.put("notify_url", wxPayConfig.getNotifyUrl());
        paramMap.put("trade_type", "JSAPI");
        paramMap.put("openid", wechatUserMiniOpenid.getMiniOpenid());

        // 生成签名
        String sign = MiniWxPayUtil.generateSignature(paramMap, wxPayConfig.getApiKey());
        paramMap.put("sign", sign);

        // 发送下单请求
        String xmlParam = MiniWxPayUtil.mapToXml(paramMap);
        String xmlResult = HttpUtil.post(UNIFIED_ORDER_URL, xmlParam);
        Map<String, String> resultMap = MiniWxPayUtil.xmlToMap(xmlResult);
        String returnCode = resultMap.get("return_code");
        String resultCode = resultMap.get("result_code");

        // 6. 检查返回结果
        if (!"SUCCESS".equals(returnCode)) {
            throw new Exception("微信支付请求失败: " + resultMap.get("return_msg"));
        }
        if (!"SUCCESS".equals(resultCode)) {
            throw new Exception("微信支付业务失败: " + resultMap.get("err_code_des"));
        }
        // 7. 提取 prepay_id
        String prepayId = resultMap.get("prepay_id");
// 先验证签名
        String returnSign = resultMap.get("sign");
        Map<String, String> signCheckMap = new HashMap<>(resultMap);
        signCheckMap.remove("sign");
        String calcSign = MiniWxPayUtil.generateSignature(signCheckMap, wxPayConfig.getApiKey());
        if (!returnSign.equals(calcSign)) {
            throw new RuntimeException("签名验证失败");
        }

// 签名验证通过后再存储订单
        // 8. 存储订单信息到数据库
        WechatUser wechatUser = wechatUserMapper.findByOpenId(openid);
        if (wechatUser!=null){
            if (!Objects.equals(wechatUser.getNickname(),null)){
                order.setNickName(wechatUser.getNickname());
            }
        }
        order.setOrderId(orderId);
        order.setOutTradeNo(orderId);
        order.setTransactionId(prepayId); // 设置微信支付订单号
        order.setPayStatus("待支付"); // 设置支付状态
        order.setPayTime(new Date()); // 设置支付时间
        order.setCreateTime(new Date()); // 设置创建时间
        order.setMiniOffType("1");
        orderMapper.insert(order); // 插入订单到数据库

        return resultMap;
    }

    public Map<String, String> getJsApiParams(String prepayId) throws Exception {
        Map<String, String> jsApiParams = new HashMap<>();
        jsApiParams.put("appId", wxPayConfig.getAppId());
        jsApiParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
        jsApiParams.put("nonceStr", MiniWxPayUtil.generateNonceStr());
        jsApiParams.put("package", "prepay_id=" + prepayId);
        jsApiParams.put("signType", "MD5");
        
        String paySign = MiniWxPayUtil.generateSignature(jsApiParams, wxPayConfig.getApiKey());
        jsApiParams.put("paySign", paySign);
        return jsApiParams;
    }

    private String generateOrderNo(String merId) {
        // 生成商户订单号
        // 获取当前时间戳（精确到秒）
        String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());

        // 生成一个随机数，用于防止同一秒内生成重复的订单号
        Random random = new Random();
        int randomNum = random.nextInt(1000);  // 生成 3 位随机数

        // 格式化成固定长度，不足补零
        String randomStr = String.format("%03d", randomNum);

        // 拼接商户订单号（商户编号 + 时间戳 + 随机数）
        String orderNumber = merId + timestamp + randomStr;

        return orderNumber;
    }
}